﻿// Brandon Haynes - http://brandonhaynes.org
// Copyright (c) 2008
// by Brandon Haynes

// Please refer to the project license, located at http://www.codeplex.com/DNNLocalization/license

// The above copyright notice and this permission notice shall be included in all copies or substantial portions 
// of the Software.

//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
//INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
//DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
//SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
//SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
//WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 
//USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 

using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Text.RegularExpressions;

namespace BrandonHaynes.DotNetNukeResXBuildProvider
	{
	public class ResourcePathMetadata
		{
		#region Public Constants
		public static string PatternWithCulture
			{
			get
				{
				return @"
						(^
							(?<namespace>			
								(?:[^\.]*\.)*?		(?# One or more sets of tokens followed by a period)
								[^\.]*				(?# Followed by a final token)
							)
							\.						(?# ... and a final period, not included in capture)
						)??							(?# Zero or one namespace captures, but as few as possible - non-greedy)
						(?:(?<typeName>[^\.]*(?:\.(?:ascx|aspx))?)\.)	(?# Typename token including ascx or aspx extension)
						(?:(?<culture>[^\.]*)\.)?	(?# Capture potential culture name)
						(?:Portal-(?<portal>\d+)\.)?(?# Optionally capture portalId)
						resx
					$";
				}
			}

		public static string PatternWithoutCulture
			{
			get
				{
				return @"
						(^
							(?<namespace>
								(?:[^\.]*\.)*?		(?# One or more sets of tokens followed by a period)
								[^\.]*				(?# Followed by a final token)
							)
							\.						(?# ... and a final period, not included in capture)
						)??							(?# Zero or one namespace captures, but as few as possible - non-greedy)
						(?:(?<typeName>[^\.]*(?:\.(?:ascx|aspx))?)\.)	(?# Typename token including ascx or aspx token)
						(?:Portal-(?<portal>\d+)\.)?(?# Optionally capture portalId)
						resx
					$";
				}
			}
		#endregion

		#region Constructors
		
		public ResourcePathMetadata(string virtualPath)
			{
			int portalId;
			string fileName = Path.GetFileName(virtualPath);

			var matches = Regex.Match(fileName, PatternWithCulture, RegexOptions.IgnoreCase | RegexOptions.CultureInvariant | RegexOptions.IgnorePatternWhitespace);
			if (!matches.Success)
				throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, @"VirtualPath ""{0}"" could not be parsed.", virtualPath), "virtualPath");
			else if (!Extensions.TryGetCulture(matches.Groups["culture"].Value, out culture))
				matches = Regex.Match(fileName, PatternWithoutCulture, RegexOptions.IgnoreCase | RegexOptions.CultureInvariant | RegexOptions.IgnorePatternWhitespace);

			VirtualPath = virtualPath;
			PortalId = int.TryParse(matches.Groups["portal"].Value, out portalId) ? (int?)portalId : null;
			Namespace = MakeValidName(FormatNamespace(matches.Groups["namespace"].Value));
			TypeName = MakeValidName(matches.Groups["typeName"].Value);
			}
		
		#endregion

		#region Public Properties

		public string VirtualPath { get; private set; }
		public string Namespace { get; private set; }
		public string TypeName { get; private set; }
		public int? PortalId { get; private set; }

		private CultureInfo culture;
		public CultureInfo Culture
			{ get { return culture; } }

		private string embeddedName;
		public string EmbeddedName
			{
			get
				{
				if (embeddedName == null)
					{
					var tokens = new List<string>(4);

					if(!string.IsNullOrEmpty(Namespace))
						tokens.Add(Namespace);

					tokens.Add(TypeName);

					if (Culture != null && !Culture.Equals(CultureInfo.InvariantCulture))
						tokens.Add(culture.Name);

					tokens.Add("resources");

					// Resource must be embedded in all-lowercase characters
					embeddedName = string.Join(".", tokens.ToArray()).ToLowerInvariant();
					}

				return embeddedName;
				}
			}

		private bool? isLocal;
		public bool IsLocal
			{
			get
				{
				if (isLocal == null)
					isLocal = Regex.IsMatch(VirtualPath, "ascx|aspx");
				return isLocal.Value;
				}
			}

		public string QualifiedTypeName
			{
			get
				{
				return string.IsNullOrEmpty(Namespace) ? TypeName : string.Format(CultureInfo.InvariantCulture, "{0}.{1}", Namespace, TypeName);
				}
			}

		#endregion
		
		#region Private Support Methods

		private string FormatNamespace(string baseNamespace)
			{
			var tokens = new List<string>(4);

			if (!IsLocal)
				tokens.Add("Resources");
			
			if(!string.IsNullOrEmpty(baseNamespace))
				tokens.Add(baseNamespace);
			
			if(PortalId != null)
				tokens.Add("Portal" + PortalId.ToString());

			return string.Join(".", tokens.ToArray());
			}

		public static string MakeValidName(string name)
			{
			return Regex.Replace(name.Trim(), @"(?:^[0-9]*)|[^a-zA-Z0-9.]", "_").TrimStart('_');
			}

		#endregion
		}
	}
